package tools

import (
	"reflect"
	"runtime"
	"sync"
)

type Event struct {
	fMap sync.Map
}

func NewEvent() *Event {
	return &Event{sync.Map{}}
}

// 获取函数的唯一key
func (e *Event) getFuncKey(i interface{}) interface{} {
	return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()
}

// 已做唯一处理 向事件添加同一个函数回调 会只存储一个
func (e *Event) Add(i interface{}) {
	p := e.getFuncKey(i)
	e.fMap.Store(p, i)
}

func (e *Event) Del(i interface{}) {
	p := e.getFuncKey(i)
	e.fMap.Delete(p)
}

func (e *Event) GetCount() int {
	n := 0

	e.fMap.Range(func(key, value interface{}) bool {
		n += 1
		return true
	})
	return n
}

func (e *Event) GetAll(out interface{}) int {
	eo := make([]reflect.Value, 0)

	n := 0

	e.fMap.Range(func(key, value interface{}) bool {
		n += 1
		eo = append(eo, reflect.ValueOf(value))
		return true
	})

	ro := reflect.ValueOf(out).Elem()
	ro.Set(reflect.Append(ro, eo...))
	return n
}

type EventMap struct {
	l sync.RWMutex
	m map[interface{}]*Event
}

func NewEventMap() *EventMap {
	return &EventMap{sync.RWMutex{}, make(map[interface{}]*Event)}
}

func (em *EventMap) Add(id interface{}, i interface{}) {
	em.l.Lock()
	defer em.l.Unlock()
	event, ok := em.m[id]
	if !ok {
		event = NewEvent()
	}
	event.Add(i)
	em.m[id] = event
}

func (em *EventMap) Del(id interface{}) {
	em.l.Lock()
	defer em.l.Unlock()
	delete(em.m, id)
}

func (em *EventMap) Get(id interface{}, out interface{}) int {
	em.l.RLock()
	defer em.l.RUnlock()
	if km, ok := em.m[id]; ok {
		return km.GetAll(out)
	}
	return 0
}

func (em *EventMap) GetAll(out interface{}) int {
	em.l.RLock()
	defer em.l.RUnlock()
	cnt := 0
	for i := range em.m {
		event := em.m[i]
		cnt += event.GetAll(out)
	}
	return cnt
}

func (em *EventMap) GetAllID() []interface{} {
	em.l.RLock()
	defer em.l.RUnlock()
	r := make([]interface{}, 0)
	for i := range em.m {
		r = append(r, i)
	}
	return r
}
